ES6新特性 | 您所在的位置:网站首页 › es6 三个点语法 › ES6新特性 |
变量
(一) const 与 let以及var
1. 三者之间区别
1.变量提升
var声明 无论声明在何处,都会被视为声明在函数的最顶部
let和const声明不会提升
2.作用域
var是函数作用域, 在函数内部作用, 但是{}里是一样会提升的
let和const是块级作用域, 在{}里就形成了一个作用域
3.重复声明
var 可以重复定义
let和const不可以重复定义,否则报错
4.const常量不可修改
const 声明的变量都会被认为是常量,意思就是它的值被设置完成后就不能再修改了;
5. 如果const的是一个对象,对象所包含的值是可以被修改的。抽象一点儿说,就是对象所指向的地址没有变就行:
const student = { name: 'cc' }
student.name = 'yy';// 不报错
student = { name: 'yy' };// 报错
复制代码2. 暂时性死区
var tmp = 123;
if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
}
复制代码
上面代码中,存在全局变量tmp,但是块级作用域内let又声明了一个局部变量tmp,导致后者绑定这个块级作用域,所以在let声明变量前,对tmp赋值会报错。
有几个点需要注意: # let 关键词声明的变量不具备变量提升(hoisting)特性 # let 和 const 声明只在最靠近的一个块中(花括号内)有效 # 当使用常量 const 声明时,请使用大写变量,如:CAPITAL_CASING # const 在声明时必须被赋值 复制代码3. 建议在日常开发中,我的建议是全面拥抱let/const,一般的变量声明使用let关键字,而当声明一些配置项(类似接口地址,npm依赖包,分页器默认页数等一些一旦声明后就不会改变的变量)的时候可以使用const,来显式的告诉项目其他开发者,这个变量是不能改变的(const声明的常量建议使用全大写字母标识,单词间用下划线),同时也建议了解var关键字的缺陷(变量提升,污染全局变量等),这样才能更好的使用新语法 函数 (一) 箭头函数(Arrow Functions) ES6 中,箭头函数就是函数的一种简写形式,使用括号包裹参数,跟随一个 =>,紧接着是函数体; 1. 箭头函数对于使用function关键字创建的函数有以下区别: 箭头函数没有arguments(建议使用更好的语法,剩余运算符替代) 箭头函数没有prototype属性,不能用作构造函数(不能用new关键字调用) 箭头函数没有自己this,它的this是词法的,引用的是上下文的this,即在你写这行代码的时候就箭头函数的this就已经和外层执行上下文的this绑定了(这里个人认为并不代表完全是静态的,因为外层的上下文仍是动态的可以使用call,apply,bind修改,这里只是说明了箭头函数的this始终等于它上层上下文中的this) 2. 箭头函数最直观的三个特点 # 不需要 function 关键字来创建函数 # 省略 return 关键字 # 继承当前上下文的 this 关键字 复制代码 细节:当你的函数有且仅有一个参数的时候,是可以省略掉括号的。当你函数返回有且仅有一个表达式的时候可以省略{} 和 return; 3. 规则 使用了块语句的箭头函数不会自动返回值,你需要使用return语句将所需值返回。 不可以当作构造函数,即,不可以使用new 关键字来实例化对象,否则会抛出一个错误。 不可以使用arguments对象,更不能通过arguments对象访问传入参数,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。 不可以使用yield命令,因此箭头函数不能用作 Generator 函数. 返回的就是一个对象, 需要在外面加一个括号 var getTempItem = id = > ({id: id,}); (二) 函数的参数默认值 // ES6之前,当未传入参数时,text = 'default'; function printText(text) { text = text || 'default'; console.log(text); } // ES6; function printText(text = 'default') { console.log(text); } printText('hello'); // hello printText();// default 复制代码(三) Promise(常用)Promise作为ES6中推出的新的概念,改变了JS的异步编程,现代前端大部分的异步请求都是使用Promise实现,fetch这个web api也是基于Promise的,这里不得简述一下之前统治JS异步编程的回调函数,回调函数有什么缺点,Promise又是怎么改善这些缺点 回调函数缺点 多重嵌套,导致回调地狱 代码跳跃,并非人类习惯的思维模式 信任问题,你不能把你的回调完全寄托与第三方库,因为你不知道第三方库到底会怎么执行回调(多次执行) 第三方库可能没有提供错误处理 不清楚回调是否都是异步调用的(可以同步调用ajax,在收到响应前会阻塞整个线程,会陷入假死状态,非常不推荐) Promise针对回调函数这么多缺点,ES6中引入了一个新的概念Promise,Promise是一个构造函数,通过new关键字创建一个Promise的实例,来看看Promise是怎么解决回调函数的这些问题 在ES6 Module出现之前,模块化一直是前端开发者讨论的重点,面对日益增长的需求和代码,需要一种方案来将臃肿的代码拆分成一个个小模块,从而推出了AMD,CMD和CommonJs这3种模块化方案,前者用在浏览器端,后面2种用在服务端,直到ES6 Module出现 ES6 Module默认目前还没有被浏览器支持,需要使用babel,在日常写demo的时候经常会显示这个错误 Module特点 ES6 Module是静态的,也就是说它是在编译阶段运行,和var以及function一样具有提升效果(这个特点使得它支持tree shaking) 自动采用严格模式(顶层的this返回undefined) ES6 Module支持使用export {}导出具名的接口,或者export default导出匿名的接口心得:ES6不仅支持变量的导出,也支持常量的导出。 export const sqrt = Math.sqrt;//导出常量 心得:一条import 语句可以同时导入默认函数和其它变量。import default Method, { otherMethod } from 'xxx.js'; module.js导出解构赋值可以直接使用对象的某个属性,而不需要通过属性访问的形式使用,对象解构原理个人认为是通过寻找相同的属性名,然后原对象的这个属性名的值赋值给新对象对应的属性, 键找键,找到了就赋值了 解构数组 var arr = [1, 2, 3, 4]; let [a, b, c, d] = arr; console.log(a); // 1 console.log(b); // 2 复制代码 解构对象 var luke = { occupation: 'jedi', father: 'anakin' }; let {occupation, father} = luke; console.log(occupation); // jedi console.log(father); // anakin 复制代码 vuex使用对象解构同样建议使用,因为解构赋值语意化更强,对于作为对象的函数参数来说,可以减少形参的声明,直接使用对象的属性(如果嵌套层数过多我个人认为不适合用对象解构,不太优雅) 剩余运算符rest/扩展运算符(常用)剩余/扩展运算符同样也是ES6一个非常重要的语法,使用3个点(...),后面跟着一个含有iterator接口的数据结构 扩展运算符 以数组为例,使用扩展运算符使得可以"展开"这个数组,可以这么理解,数组是存放元素集合的一个容器,而使用扩展运算符可以将这个容器拆开,这样就只剩下元素集合,你可以把这些元素集合放到另外一个数组里面, 代替ES3中数组原型的concat方法剩余运算符最重要的一个特点就是替代了以前的arguments rest只是形参, 可以随意取名 访问函数的arguments对象是一个很昂贵的操作,以前的arguments.callee,arguments.caller都被废止了,建议在支持ES6语法的环境下不要在使用arguments对象,使用剩余运算符替代(箭头函数没有arguments,必须使用剩余运算符才能访问参数集合)剩余运算符和扩展运算符的区别就是,剩余运算符会收集这些集合,放到右边的数组中,扩展运算符是将右边的数组拆分成元素的集合,它们是相反的 在对象中使用扩展运算符 这个是ES9的语法,ES9中支持在对象中使用扩展运算符,之前说过数组的扩展运算符原理是消耗所有迭代器,但对象中并没有迭代器,我个人认为可能是实现原理不同,但是仍可以理解为将键值对从对象中拆开,它可以放到另外一个普通对象中对熟悉Java,object-c,c#等纯面向对象语言的开发者来说,都会对class有一种特殊的情怀。ES6 引入了class(类),让JavaScript的面向对象编程变得更加简单和易于理解。 class Animal { // 构造函数,实例化的时候将会被调用,如果不指定,那么会有一个不带参数的默认构造函数. constructor(name,color) { this.name = name; this.color = color; } // toString 是原型对象上的属性 toString() { console.log('name:' + this.name + ',color:' + this.color); } } var animal = new Animal('dog','white');//实例化Animal animal.toString(); console.log(animal.hasOwnProperty('name')); //true console.log(animal.hasOwnProperty('toString')); // false console.log(animal.__proto__.hasOwnProperty('toString')); // true class Cat extends Animal { constructor(action) { // 子类必须要在constructor中指定super 函数,否则在新建实例的时候会报错. // 如果没有置顶consructor,默认带super函数的constructor将会被添加、 super('cat','white'); this.action = action; } toString() { console.log(super.toString()); } } var cat = new Cat('catch') cat.toString(); // 实例cat 是 Cat 和 Animal 的实例,和Es5完全一致。 console.log(cat instanceof Cat); // true console.log(cat instanceof Animal); // true 复制代码includesincludes() 函数用来判断一个数组是否包含一个指定的值,如果包含则返回 true,否则返回false。 includes 函数与 indexOf 函数很相似,下面两个表达式是等价的: arr.includes(x) arr.indexOf(x) >= 0 复制代码接下来我们来判断数字中是否包含某个元素: 在ES7之前的做法 使用indexOf()验证数组中是否存在某个元素,这时需要根据返回值是否为-1来判断: let arr = ['react', 'angular', 'vue']; if (arr.indexOf('react') !== -1) { console.log('react存在'); } 复制代码使用ES7的includes() 使用includes()验证数组中是否存在某个元素,这样更加直观简单: let arr = ['react', 'angular', 'vue']; if (arr.includes('react')) { console.log('react存在'); } 复制代码指数操作符在ES7中引入了指数运算符**,**具有与Math.pow(..)等效的计算结果。 不使用指数操作符 使用自定义的递归函数calculateExponent或者Math.pow()进行指数运算: function calculateExponent(base, exponent) { if (exponent === 1) { return base; } else { return base * calculateExponent(base, exponent - 1); } } console.log(calculateExponent(2, 10)); // 输出1024 console.log(Math.pow(2, 10)); // 输出1024 复制代码 复制代码使用指数操作符 使用指数运算符**,就像+、-等操作符一样: console.log(2**10);// 输出1024 复制代码1 |
CopyRight 2018-2019 实验室设备网 版权所有 |